<template>
  <basic-container>
    <basic-header :title="detailTitle">
      <el-button @click="$router.go(-1)">返回</el-button>
    </basic-header>
    <el-form :model="formData" ref="form" label-width="160px" class="detail-form" :rules="detailType === 'view' ? {} : formRules" :hide-required-asterisk="detailType === 'view'">
      <template v-for="(item, index) in detailOption.form">
        <el-form-item v-if="item.show ? item.show(formData, detailType, $store) : true" :label="item.label" :prop="item.prop" :key="index + '-form'" :class="{'top-line': item.topLine}">
          <!--预览-->
          <div class="detail-form-input" v-if="item.view && detailType === 'view'">{{item.view(formData, $store)}}</div>
          <!--图片上传-->
          <template v-else-if="item.type==='image'">
            <el-input v-model="formData[item.prop]" v-show="false" style="width:1;height:1;z-index:-1;position:abslute" />
            <image-upload :disable="disable" :image.sync="formData[item.prop]" :imageKey.sync="formData[item.upKey]" :repeat="item.repeat" :accept="item.accept" :putting.sync="attachRefuse[item.prop]" />
          </template>

          <!--文本输入框-->
          <div class="detail-form-input" v-else-if="item.type==='text'">
            <div class="detail-form-text" v-if="disable">{{item.view ? item.view(formData) : formData[item.prop]}}</div>
            <el-input v-else v-model="formData[item.prop]" :clearable="true" :placeholder="item.placeholder" />
          </div>

          <!--数字文本输入框-->
          <div class="detail-form-input" v-else-if="item.type==='number'">
            <div class="detail-form-text" v-if="disable">{{formData[item.prop]}}</div>
            <el-input v-else v-model.number="formData[item.prop]" :clearable="true" :placeholder="item.placeholder" />
          </div>

          <!--带后缀的文本输入框-->
          <div class="detail-form-input" v-else-if="item.type==='sub-text'">
            <div class="detail-form-text" v-if="disable">{{`${formData[item.prop]}${item.option(formData)}`}}</div>
            <template v-else>
              <el-input v-model="formData[item.prop]" :clearable="true" :placeholder="item.placeholder" />
              <span class="detail-form-sub">{{item.option(formData)}}</span>
            </template>
          </div>

          <!--带后缀的数字文本输入框-->
          <div class="detail-form-input" v-else-if="item.type==='sub-number'">
            <div class="detail-form-text" v-if="disable">{{`${formData[item.prop]}${item.option(formData)}`}}</div>
            <template v-else>
              <el-input v-model.number="formData[item.prop]" :clearable="true" :placeholder="item.placeholder" />
              <span class="detail-form-sub">{{item.option(formData)}}</span>
            </template>
          </div>
          <!--密码输入框-->
          <div class="detail-form-input" v-else-if="item.type==='password'">
            <div class="detail-form-text" v-if="disable">********</div>
            <el-input v-else type="password" v-model="formData[item.prop]" :placeholder="item.placeholder || '请输入密码'" />
          </div>
          <!--复选框-->
          <template v-else-if="item.type==='checkbox'">
            <el-input v-model="formData[item.prop]" v-show="false" style="width:1;height:1;z-index:-1;position:abslute" />
            <checkbox-detail v-model="formData[item.prop]" :options="item.option(formData, $store)" :type="item.check_type" :disable="disable" @change="(value) => handleChangeCheckbox(value, item)" />
          </template>

          <!--评分-->
          <template v-else-if="item.type==='rate'">
            <el-rate style="display: inline-block" v-model="formData[item.prop]" :disabled="disable" />
          </template>

          <!--文本输入框-->
          <div class="detail-form-input" v-else-if="item.type==='textarea'">
            <el-input v-model="formData[item.prop]" type="textarea" :placeholder="item.placeholder" :autosize="{ minRows: 3, maxRows: 5}" :maxlength="item.maxLength" :disabled="disable" :show-word-limit="item.maxLength" />
          </div>

          <!--下拉选择框-->
          <div class="detail-form-input" v-else-if="item.type==='select'">
            <div class="detail-form-text" v-if="disable">{{formData[item.prop] | reviewSelectValue(item.option(formData, $store))}}</div>
            <el-select v-else v-model="formData[item.prop]" :clearable="true" :placeholder="item.placeholder" @change="(value) => handleChange(value, item)">
              <el-option v-for="(opt, id) in item.option(formData, $store)" :key="id" :value="opt.value" :label="opt.label" />
            </el-select>
          </div>

          <!--下日期选择框-->
          <div class="detail-form-input" v-else-if="item.type==='date'">
            <div class="detail-form-text" v-if="disable">{{new Date(formData[item.prop]) | dateFormat('yyyy-mm-dd')}}</div>
            <el-date-picker v-else v-model="formData[item.prop]" type="date" placeholder="选择日期" />
          </div>

          <!--时间日期选择框-->
          <div class="detail-form-input" v-else-if="item.type==='datetime'">
            <div class="detail-form-text" v-if="disable">{{new Date(formData[item.prop]) | dateFormat('yyyy-mm-dd HH:MM:SS')}}</div>
            <el-date-picker v-else v-model="formData[item.prop]" type="datetime" placeholder="选择日期时间" />
          </div>
          <!--文本输入框-->
          <div class="detail-form-edit" v-else-if="item.type==='edit'">
            <div class="detail-review-box" v-if="disable" v-html="formData[item.prop]" />
            <template v-else>
              <el-input v-model="formData[item.prop]" v-show="false" style="width:1;height:1;z-index:-1;position:abslute" />
              <Editor v-model="formData[item.prop]" />
            </template>
          </div>
        </el-form-item>
      </template>

      <el-form-item v-if="disable &&detailOption.viewFooter" class="detail-form-bottom">
        <el-button :type="detailOption.viewFooter.leftBtn" @click="handleClickLeftBtn">{{detailOption.viewFooter.leftBtnText}}</el-button>
        <el-button :type="detailOption.viewFooter.rightBtn" @click="handleClickRightBtn">{{detailOption.viewFooter.rightBtnText}}</el-button>
      </el-form-item>
      <el-form-item v-if="disable && detailOption.designate && detailOption.designate.link(formData)" class="detail-form-bottom">
        <el-button v-if="detailOption.designate" @click="handleDesignate">指派</el-button>
      </el-form-item>
      <el-form-item v-if="!disable" class="detail-form-bottom">
        <el-button @click="$router.go(-1)">取消</el-button>
        <el-button type="primary" :loading="isSaving" @click="submitForm">保存</el-button>
      </el-form-item>
    </el-form>
  </basic-container>
</template>
<script>
import detailOptionMap from "@/const/detail";
import ImageUpload from "@/components/Upload";
import Editor from "@/components/Editor";
import CheckboxDetail from "@/components/CheckboxDetail";
import { mapState, mapActions, mapMutations } from "vuex";
import detailMixin from "@/mixins/detail";
import { dateFormat } from "@/util/date";

export default {
  name: "detail",
  components: { ImageUpload, Editor, CheckboxDetail },
  mixins: [detailMixin],
  filters: {
    // 還有些問題，无法规避级联操作的解耦
    reviewSelectValue(value, options) {
      for (let i = 0; i < options.length; i++) {
        if (options[i].value == value) {
          return options[i].label;
        }
      }
      return value;
    },
    dateFormat(value, format) {
      return dateFormat(value, format);
    }
  },
  computed: {
    ...mapState("table", ["currentData"]),
    ...mapState("@@loading", {
      loading: state => state.effects["table/GetDetailData"]
    }),
    $attachRefuse() {
      // 检查attachRefuse对象是否不为空用于阻断提交，如图片上传中，attachRefuse不为空
      let refuseResult = null;
      Object.keys(this.attachRefuse).forEach(key => {
        if (this.attachRefuse[key]) {
          refuseResult = this.attachRefuse[key];
        }
      });
      return refuseResult;
    }
  },
  data() {
    return {
      detailOption: {},
      disable: false,
      formData: {},
      detailTitle: "",
      formRules: {},
      attachRefuse: {}
    };
  },
  async created() {
    const { action, type, id } = this.$route.query;
    // 如果不是添加，拉取detail
    if (type !== "add" && !id) {
      this.$router.go(-1);
      return;
    }

    if (type !== "add") {
      await this.GetDetailData({ action, id });
    }
    this.disable = type === "view";
    this.action = action;
    this.detailType = type;

    this.initDetailData(action);
    this.initFormRules();
    this.initTitle(type);
  },
  methods: {
    ...mapMutations({
      setCurrentData: "table/SET_CURRENT_DATA"
    }),
    ...mapActions("table", ["GetDetailData", "saveDetailData"]),
    initTitle(type) {
      const title = this.detailOption.title;
      this.detailTitle =
        {
          view: `${title}详情`,
          edit: `编辑${title}`,
          add: `新增${title}`
        }[type] || title;
    },
    initDetailData(action) {
      const detailOption = detailOptionMap[action] || {};
      const formData = JSON.parse(JSON.stringify(this.currentData));
      let nextCascader;
      let nextValue;
      detailOption.form &&
        detailOption.form.forEach(option => {
          if (option.auto_dispatch) {
            this.$store
              .dispatch(option.auto_dispatch, option.auto_payload)
              .then(sort => {
                if (option.isSort && !formData[option.prop]) {
                  this.$nextTick(() => {
                    this.$set(this.formData, option.prop, sort);
                    console.log("------- is test ----");
                  });
                }
              });
          }
          // 级联操作获取字典
          if (nextCascader === option.prop && option.dispatch && nextValue) {
            this.$store.dispatch(option.dispatch, nextValue);
          }
          // 定义下一个级联操作对象和值
          if (option.cascader) {
            nextValue = formData[option.prop];
            nextCascader = option.cascader;
          }
          // 新增checkbox绑定数据需要定义为数组
          if (!formData[option.prop] && option.type === "checkbox") {
            formData[option.prop] = [];
          }
          if (typeof option.check_value === "function") {
            let matchProp = option.prop.match(/^\${([^}]*)/)[1];
            formData[option.prop] = option.check_value(formData[matchProp]);
          }
          if (
            typeof option.edit_value === "function" &&
            formData[option.prop]
          ) {
            formData[option.prop] = option.edit_value(formData[option.prop]);
          }
          console.log(option.prop, formData[option.prop]);
        });

      this.detailOption = detailOption;
      this.formData = formData;
    },
    initFormRules() {
      let rules = {};
      this.detailOption.form &&
        this.detailOption.form.forEach(option => {
          let currRule = option.rule
            ? option.rule.length
              ? option.rule
              : [option.rule]
            : [];
          if (option.greater) {
            // 不能大于某个值的rule
            const greaterValidate = (rule, value, callback) => {
              if (!this.formData[option.greater]) {
                callback();
                return;
              }
              let greater, littler;
              if (typeof value !== "number") {
                [greater, littler] = [
                  new Date(value).getTime(),
                  new Date(this.formData[option.greater]).getTime()
                ];
                if (greater < littler) {
                  callback("不能小于开始时间");
                  return;
                }
                callback();
                return;
              }

              [greater, littler] = [value, this.formData[option.greater]];

              if (greater < littler) {
                callback("不能小于开始的");
                return;
              }

              callback();
            };

            currRule.push({ validator: greaterValidate, tigger: "change" });
          }
          if (option.equal) {
            const equlaValidate = (rule, value, callback) => {
              if (value !== this.formData[option.equal]) {
                callback(option.equalText || "两次输入的值不同");
                return;
              }
              callback();
            };
            currRule.push({ validator: equlaValidate, tigger: "blur" });
          }
          if (this.detailType === "edit" && option.ruleOnEdit) {
            currRule.push(...option.ruleOnEdit);
          }
          if (this.detailType === "add" && option.ruleOnAdd) {
            currRule.push(...option.ruleOnAdd);
          }
          rules[option.prop] = currRule;
        });
      this.formRules = rules;
    },
    submitForm() {
      if (this.$attachRefuse && this.$attachRefuse !== "") {
        this.$message({
          type: "warning",
          message: this.$attachRefuse
        });
        return;
      }
      this.$refs["form"].validate(valid => {
        if (valid) {
          this.saveDetailData({ action: this.action, formData: this.formData })
            .then(() => {
              this.$message({
                type: "success",
                message: this.detailType === "add" ? "添加成功" : "修改成功"
              });
              setTimeout(() => this.$router.go(-1), 1500);
            })
            .catch(error => {
              this.$message({
                type: "error",
                message: error.message || String(error)
              });
            });
        }
      });
    },
    handleChange(value, item) {
      // 条件赋值
      if (item.assignValue) {
        Object.keys(item.assignValue).forEach(key => {
          if (this.formData[key]) {
            this.formData[key] = item.assignValue[key];
          }
          if (key.indexOf(":") > -1) {
            let [conditionKey, conditionValue] = key.split(":");
            if (value == conditionValue) {
              this.formData[conditionKey] &&
                (this.formData[conditionKey] = item.assignValue[key]);
            }
          }
        });
      }
      // 级联操作
      if (item.cascader) {
        let nextCascader = item.cascader;
        let nextValue = value;
        this.detailOption.form.forEach(option => {
          // 找到级联对应的prop
          if (nextCascader === option.prop) {
            if (option.dispatch) {
              this.$store.dispatch(option.dispatch, nextValue);
            }
            nextValue = "";
            nextCascader = option.cascader;
            // 清空级联值
            this.$set(this.formData, option.prop, nextValue);
            // 重新拉取对应的字典树
          }
        });
      }
    },
    handleChangeCheckbox(value, item) {
      if (item.cascader) {
        let nextCascader = item.cascader;
        this.detailOption.form.forEach(option => {
          // 找到级联对应的prop
          if (nextCascader === option.prop) {
            if (option.dispatch && value && value.length) {
              this.$store.dispatch(option.dispatch, value);
            }
          }
        });
      }
    },
    handleDesignate() {
      if (!this.formData.id) {
        this.$message({
          type: "error",
          message: "未知错误"
        });
        return;
      }
      this.setCurrentData({ designateFrom: this.formData.id });
      this.$router.push(this.detailOption.designate.path);
    },
    handleClickLeftBtn() {
      const [promise, args, succMsg] = this.detailOption.viewFooter.leftAction;
      if (promise) {
        promise(this.$route.query.id, args)
          .then(() => {
            this.$message({
              type: "success",
              message: succMsg
            });
            setTimeout(() => {
              this.$router.go(-1);
            }, 2000);
          })
          .catch(error => {
            this.$message({
              type: "error",
              message: error.message || String(error)
            });
          });
      }
    },
    handleClickRightBtn() {
      const [promise, args, succMsg] = this.detailOption.viewFooter.rightAction;
      if (promise) {
        promise(this.$route.query.id, args)
          .then(() => {
            this.$message({
              type: "success",
              message: succMsg
            });
            setTimeout(() => {
              this.$router.go(-1);
            }, 2000);
          })
          .catch(error => {
            this.$message({
              type: "error",
              message: error.message || String(error)
            });
          });
      }
    }
  }
};
</script>
<style lang="scss">
.el-checkbox {
  margin-right: 30px;
  & + & {
    margin-left: 0 !important;
  }
}
.el-textarea .el-input__count {
  line-height: 1.2;
}
.detail-image-view {
  max-width: 100%;
}
</style>


